package com.ncmem.up6.biz;

import com.google.gson.Gson;
import com.ncmem.up6.database.DBConfig;
import com.ncmem.up6.database.DBFile;
import com.ncmem.up6.database.DbFolder;
import com.ncmem.up6.database.DbHelper;
import com.ncmem.up6.model.FileInf;
import com.ncmem.up6.sql.SqlSeter;
import com.ncmem.up6.sql.SqlTable;
import com.ncmem.up6.utils.PathTool;
import org.apache.commons.lang.StringUtils;

import java.io.*;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class FolderSchemaDB {

    FileInf m_root;
    List<FileInf> m_files;
    List<FileInf> m_folders;
    Map<String,FileInf> m_dirs;//pathSvr,fd

    //保存所有文件的父级目录信息
    public void parseParent()
    {
        for(int i=0 , l = m_files.size() ; i < l ; ++i)
        {
            FileInf file = (FileInf)m_files.get(i);
            FileInf dir = new FileInf();
            dir.id = file.pid;
            dir.uid = this.m_root.uid;
            dir.pidRoot = file.pidRoot;
            dir.pathSvr = file.parentDir();
            dir.pathRel = dir.pathSvr.replace(this.m_root.pathSvr, "");
            dir.nameLoc = PathTool.getName(dir.pathSvr);
            dir.nameSvr = dir.nameLoc;
            dir.fdChild = true;
            dir.complete = true;

            //添加不存在的目录
            if(!this.m_dirs.containsKey(dir.pathSvr))
            {
                this.m_folders.add(dir);
                this.m_dirs.put(dir.pathSvr, dir);
            }
        }
    }

    //递归分析和保存父级目录
    public void parseDirs()
    {
        for(int i=0 , l = m_folders.size() ; i < l ; ++i)
        {
            FileInf file = m_folders.get(i);

            String dir = file.pathSvr;
            int pos = dir.indexOf("/", this.m_root.pathSvr.length());
            while( -1 != pos)
            {
                FileInf fd = new FileInf();
                fd.uid = this.m_root.uid;
                fd.pathSvr = dir.substring(0, pos);
                fd.pidRoot = this.m_root.id;
                fd.pathRel = fd.pathSvr.replace(this.m_root.pathSvr, "");
                fd.nameLoc = PathTool.getName(fd.pathSvr);
                fd.nameSvr = fd.nameLoc;
                fd.complete = true;
                fd.fdChild = true;

                //不存在
                if(!this.m_dirs.containsKey(fd.pathSvr))
                {
                    fd.id = PathTool.guid();
                    this.m_folders.add(fd);//添加目录
                    this.m_dirs.put(fd.pathSvr, fd);//添加字典
                }

                pos = dir.indexOf("/", pos+1);
            }
        }
    }

    //更新所有目录的PID
    public void updatePID()
    {
        //更新目录pid
        for(int i=1 , l = m_folders.size() ; i < l ; ++i)
        {
            FileInf fd = (FileInf)m_folders.get(i);
            if( StringUtils.isEmpty(fd.pid) )
            {
                String dir = fd.parentDir();
                FileInf pfd = (FileInf)this.m_dirs.get(dir);
                fd.pid = pfd.id;
            }
        }

        //更新文件pid
        for(int i = 0,l=this.m_files.size();i<l;++i)
        {
            FileInf f = this.m_files.get(i);
            String dir = f.parentDir();
            FileInf fd = this.m_dirs.get(dir);
            f.pid = fd.id;
        }
    }

    /// <summary>
    /// 更新文件和目录相对路径
    ///     1.增加根目录前缀
    /// </summary>
    void updatePathRel()
    {
        for(FileInf fd : this.m_folders)
        {
            if (!StringUtils.isEmpty(fd.pid) )
                //更新相对路径->增加根目录前缀
                fd.pathRel = PathTool.combin(this.m_root.pathRel , fd.pathRel);
        }

        for(FileInf f : this.m_files)
        {
            f.pathRel = PathTool.combin( this.m_root.pathRel , f.pathRel);
        }
    }

    protected void loadFiles(FileInf dir) throws IOException
    {
        //加载folder.txt
        File f = new File(dir.schemaFile());
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f),"UTF-8"));
        String line = null;
        Gson g = new Gson();
        Map<String, Boolean> dic = new HashMap<String,Boolean>();

        while( (line = br.readLine() )!=null )
        {
            FileInf item = g.fromJson(line,FileInf.class);
            item.uid = this.m_root.uid;

            //防止重复添加
            if(!dic.containsKey(item.id))
            {
                item.complete=true;
                item.perSvr = "100%";
                item.scaned=true;
                if(item.fdTask)
                {
                    this.m_folders.add(item);
                    this.m_dirs.put(item.pathSvr, item);
                }
                else
                {
                    item.fdChild=true;
                    item.sizeLoc = item.formatSize(item.lenLoc);
                    item.lenSvr = item.lenLoc;
                    this.m_files.add(item);
                }
                dic.put(item.id,true);
            }
        }
        br.close();
    }

    //保存到数据库
    public void save(FileInf dir) throws IOException, SQLException, ParseException, IllegalAccessException {
        this.m_root = dir;
        this.m_files = new ArrayList<FileInf>();
        this.m_folders = new ArrayList<FileInf>();
        this.m_dirs = new HashMap<String,FileInf>();

        //加载层级信息
        this.loadFiles(dir);

        //分析
        this.parseParent();
        this.parseDirs();
        this.updatePID();
        this.updatePathRel();

        //取消根目录
        this.m_folders.remove(0);
        DbFolder.build().addBatch(this.m_folders);
        DBFile.build().addBatch(this.m_files);
    }


    /// <summary>
    /// 覆盖文件
    /// </summary>
    /// <param name="files"></param>
    protected void cover_files() throws ParseException, IllegalAccessException, SQLException {
        SqlTable.build("up6_files").updates(this.m_files,
                SqlSeter.build().set("f_deleted",true),
                "f_pathRel");
    }

    /// <summary>
    /// 覆盖文件夹
    /// </summary>
    /// <param name="files"></param>
    protected void cover_folders() throws ParseException, IllegalAccessException, SQLException {
        SqlTable.build("up6_folders").updates(this.m_folders,
                SqlSeter.build().set("f_deleted",true),
                "f_pathRel");
    }

    public void cover() throws ParseException, IllegalAccessException, SQLException {
        this.cover_files();
        this.cover_folders();
    }
}
